前置處理器,或稱預處理器,於編譯前進行。
例如常用的 #include
和 #define
,#define
即 巨集/宏 (marco) 。
以 #
開頭都是前置處理器,其他的例子如
例如: #if
, #endif
, #else
, #elif
,#ifdef
, #ifndef
, #error
, #pragma
, #typedef
等等。
詳情可參考 microsoft 的 C/C++ 前置處理器參考
#define
:巨集和指標可謂是 C 語言的精髓,
依靠它們可以創造無限可能,極為博大精深。
巨集可以節省工作量,同時增加可讀性,使代碼變得優雅。
即使巨集的本身不優雅、可讀。
基礎知識就不說了,以下講述 #
和 ##
前置處理器運算子的功能,
詳情亦可參考 microsoft 的 前置處理器運算子
#
:#
— 字串化運算子,
放在巨集參數前,展開時中參數兩端加入 "
,使其字串化。
例子:
#define str(x) #x
使用 str( 9qwe7 h5d1v3jk6w )
會被展開為
" 9qwe7 h5d1v3jk6w "
另外,根據定義,
如果在字串常值中使用引數包含通常需要逸出序列時 (例如引號 (") 或反斜線 () 字元),必要的逸出反斜線字元就會自動插入至該字元之前。
#
會自動添加逸出反斜線字元(\)
利用此特性可以簡化大量需要逸出反斜線的字串。
例如 我要輸入 the "\" mean escaped character.
作為字串
正常: "the \"\\\" mean escaped character."
,
巨集: str(the "\" mean escaped character.)
。
某程度上來說,可讀性會較好。
還有常見的檔案路徑,如果我要輸入 D:\User\Documents\C_Test.txt
作為檔案路徑。
正常: "D:\\User\\Documents\\C_Test.txt"
巨集: str(D:\User\Documents\C_Test.txt)
。
可以不用考慮要不要加 \
,也可以打少一些字元。
##
:##
— 語彙基元帶入的運算子,
這名字是 microsoft 改的,有時稱為「合併」運算子。
可以合併文字,例子:
#define mix(x) abc##x
使用 mix(d)
會被展開為 abcd
意義何在呢?因為識別字是以空格作為分隔,若果
#define mix(x) abcx
前置處理器無法辨認出 x
,它只看到有 abcx
這個識別字。
加入 ##
可以令它識別出 巨集參數 並將其合併。
另外, ##
前後的空格可有可無,
即 abc##x
等價 abc ## x
一旦在使用了 #
或 ##
在 巨集中,
其巨集參數是 是另一個 巨集/宏 ,
將會阻止另一個 巨集/宏 的展開。
例子:
#define foo abc
#define foo2(x) x##123
foo2(foo)
的結果並不會是 abc123
,
不會展開作為參數的巨集 foo
,
所以結果是 foo123
。
可參看 C宏展开的几个注意事项 - nanoix9 - 博客园,
沒仔細看,貌似很詳細。
回來看了一下,經過測試,我發現這篇文章,C宏展开的几个注意事项 - nanoix9 - 博客园中,
【这个时候,逗号视为合法分隔符。】的部分好像是錯的。
不知道,注意一下,可能是我的編譯器跟他不同。
...
= = 超久之後回來了...
原來 VS(Visual Studio) 把這種附有逗號的展開視為整體,單個參數。
所以 【这个时候,逗号视为合法分隔符。】的部分好像是錯的。在 gcc 下正確的。
VS 下錯誤。
有一些預先定義在前置處理器中的巨集:__LINE__
:從原始檔開頭起算, __LINE__
所在的行數__FILE__
:檔案名稱(字串常數)__DATE__
:以 Mmm dd yyyy 格式(eg. Oct 31 2018),表示編譯時的日期__TIME__
:以 hh:mm:ss 格式,表示編譯時的時間 (字串常數)__STDC__
:若 1 ,表示編譯器遵循 ISO C 標準__STDC_VERSION__
:若支援 C99,數值為 199901L
, 若支援 C11,數值為 201112L
。__func__
:函式名稱 (C99)
...還有很多,不全部列出。
__LINE__
和 __FILE__
常用於錯誤訊息。__func__
也是,不過是 C99 才支援。
循序漸進,很好,很詳細,很深入。
學到不少新技術,
推薦推薦~!
預處理器 - 維基百科,自由的百科全書
https://zh.wikipedia.org/zh-hk/%E9%A2%84%E5%A4%84%E7%90%86%E5%99%A8
C/C++ 前置處理器參考
https://msdn.microsoft.com/zh-tw/library/y4skk93w.aspx
前置處理器運算子
https://msdn.microsoft.com/zh-tw/library/wy090hkc.aspx
C宏展开的几个注意事项 - nanoix9 - 博客园
http://www.cnblogs.com/aquastone/p/c-macro-expansion.html
C 語言程式設計教學:前置處理器 (Preprocessor) | Michael Chen 的技術文件分享
https://cwchen.tw/c-prog/preprocessor/
宏定义的黑魔法 - 宏菜鸟起飞手册
https://onevcat.com/2014/01/black-magic-in-macro/